package pogvue.gui;

import pogvue.datamodel.*;
import pogvue.gui.schemes.ColourSchemeI;
import pogvue.gui.schemes.ResidueProperties;

import java.awt.*;
import java.util.Hashtable;
import java.util.Vector;

public final class KmerFrequencyRenderer implements RendererI {

    private final Color grayRed    = new Color(237,171,173);
    private final Color grayBlue   = new Color(123,145,166);
    private final Color grayYellow = new Color(255,250,165);
    private final Color grayGreen  = new Color(115,177,138);
            
    private final Color duskyRed   = new Color(255,84,90);
    final Color duskyGreen = new Color(93,252,128);
    private final Color duskyBlue  = new Color(93,128,255);
  
    public Color getResidueBoxColour(ColourSchemeI cs, SequenceI seq, int i) {
	Color c = cs.findColour(seq,seq.getSequence(i,i+1),i,null);
	return c;
    }
    
    public void drawSequence(Graphics g,ColourSchemeI cs,SequenceI seq,int start, int end, int x1, int y1, double width, int height,boolean showScores, boolean displayBoxes, boolean displayText,Vector pid, int seqnum,AlignViewport av, Hashtable props, int intpid[][]) {
	
	int i      = start;
	int length = seq.getLength();

	Color currentColor = Color.white;

	g.setColor(Color.black);

        int prev = -1;


	GFF gff;

	Vector feat = new Vector();

	for (int k = 0; k < av.getAlignment().getSequences().size(); k++) {
	    if (av.getAlignment().getSequences().elementAt(k) instanceof GFF) {
		gff = (GFF)av.getAlignment().getSequences().elementAt(k);
		feat = gff.overlaps(start,end);
	    }
	}

	KmerFrequency kfreq = null;

	//	pid = AAFrequency.calculate(av.getAlignment().getSequences(),
	//			    start,end);

	int pixel = -1;

	Vector    inserts = null;
	Hashtable inserts_by_coord = null;
	Sequence   topseq = (Sequence)av.getAlignment().getSequences().elementAt(0);

	kfreq = av.getKmerFrequency();

	if (seq instanceof GappedSequence) {
	    inserts = ((GappedSequence)seq).inserts;
	    inserts_by_coord = ((GappedSequence)seq).inserts_by_coord;
	}


	while (i <= end && i < length) {

	    Hashtable h = (Hashtable)pid.elementAt(i-start);
            char c = seq.getCharAt(i);
	    
	    String topresstr = (String)(h.get("maxResidue"));
	    
	    char tr = topresstr.charAt(0);

	    int newpixel = x1 + (int)((i-start)*width);
	    
	    if (seq instanceof GappedSequence) {
	      String insert = "";
	      int    mod = 0;

	      if (inserts_by_coord.containsKey(new Integer(i))) {
		insert = (String)inserts_by_coord.get(new Integer(i));
	        mod    = insert.length()%3;
	      } else if (inserts_by_coord.containsKey(new Integer(-i))) {	       
		insert = (String)inserts_by_coord.get(new Integer(-i));
	        mod    = insert.length()%3;
	      }
	      if (insert.length() > 0) {
		if (mod != 0) {
		  g.setColor(duskyRed);
		} else {
		  g.setColor(duskyBlue);
		}
		g.fillRect((int)(newpixel-width),y1,2,height-1);
		
		int tmpsize = insert.length();
		
		if (tmpsize > 10) {
		  tmpsize = 10;
		}
		
		g.fillRect((int)(newpixel-width)-tmpsize/2,y1-tmpsize,tmpsize,tmpsize);
	      }
	    }

            if ( c != '-') {

		if (seq == topseq) {
		    // Colour by kmer frequencey here
		    int half = kfreq.getKmerSize()/2;
		    if (i-half >= 0 &&
			i+half < seq.getLength()) {
			String kmer  = seq.getSequence().substring(i-half,i+half);

			//int    count = (int)(kfreq.getKmerCount()*kfreq.getNonConservedCount(kmer)/kfreq.getNonConservedTotal());
			int count = kfreq.getRelativeCount(kmer);

			if (count > 100) {
			    g.setColor(Color.red);
			}
			if (count == 100) {
			    g.setColor(Color.pink);
			} 
			if (count < 100) {
			    g.setColor(Color.blue);
			}
			if (count == 0) {
			    g.setColor(Color.lightGray);
			}

			//System.out.println("Kmer " + kmer + " " + count);
			
			//if (count == 0) {
			//    g.setColor(Color.lightGray);
			//} else if (count < 2) {
			//    g.setColor(Color.yellow);
			//} else if (count < 3) {
			//    g.setColor(Color.pink);
			//} else if (count < 4) {
			//    g.setColor(Color.orange);
			//} else if (count < 5) {
			//    g.setColor(Color.magenta);
			//} else if (count < 10) {
			//    g.setColor(Color.red);
			//}
		    }
		} else {
		    if (c == tr) {
			g.setColor(Color.lightGray);
		    } else {
			if (c == 'A') {
			    g.setColor(grayGreen);             
			} else if (c == 'C') {                 
			    g.setColor(grayRed);
			} else if (c == 'G') {
			    g.setColor(grayBlue);              
			} else if (c == 'T') {           
			    g.setColor(grayYellow);      
			} else if (c == '.') {
			    g.setColor(Color.pink);
			} else if (c == '=') {
			    g.setColor(Color.orange);
			}
			g.setColor(Color.gray);
		    }
		}
		    
		if (pixel == -1 || newpixel > pixel || i == end) {
		    g.fillRect(newpixel,y1,(int)(width+1),height-2);
		    
		    if (width > 5) {
			g.setColor(Color.black);
			g.drawString(seq.getSequence().substring(i,i+1),x1+(int)(width*(i-start)),y1+3*height/4);
		  }
		}

		// Now look for splices
		for (int j = 0; j < feat.size(); j++) {
		    SequenceFeature sf = (SequenceFeature)feat.elementAt(j);
		    
		    // Exon starts first
		    if (sf.getStart() == i+2 || 
			sf.getStart() == i+1) {

			if (topseq.getCharAt(i) == seq.getCharAt(i)) {
			    g.setColor(Color.magenta);
			} else {
			    g.setColor(Color.cyan);
			}
			g.fillRect(newpixel,y1,(int)(width+1),height-4);
			
			
			if (width > 5) {
			    g.setColor(Color.black);
			    g.drawString(seq.getSequence().substring(i,i+1),x1+(int)(width*(i-start)),y1+3*height/4);
			    
			} 
		    }

		    // Now ends
		    if (sf.getEnd() == i-1 ||
			sf.getEnd() == i-2) {

			if (topseq.getCharAt(i) == seq.getCharAt(i)) {
			    g.setColor(Color.magenta);
			} else {
			    g.setColor(Color.cyan);
			}
			g.fillRect(newpixel,y1,(int)(width+1),height-4);
			
			if (width > 5) {
			    g.setColor(Color.black);
			    g.drawString(seq.getSequence().substring(i,i+1),x1+(int)(width*(i-start)),y1+3*height/4);
			    
			} 
			
		    } 

		    // Now let's see about syn/nonsyn changes

		    if (av.getTranslateExons() == true) {
			if (i-2 >= sf.getStart() &&
			    i <= sf.getEnd() &&
			    sf instanceof Exon) {
			    
			    int phase = 0;//((Exon)sf).getPhase();
			    //System.out.println("Name " + seq.getName());
			    //			    int hphase = ((Exon)sf).getHPhase(seq.getName());

			    
			    //System.out.println("Hphase = " + hphase + " " + phase);

			    //if (hphase != -1) {
			      //phase = hphase;
			    //}

			    if (sf.getStrand() == 1) {
			      int pos   = (i-2 - sf.getStart() - (3-phase))%3;
				
				if (pos == 0) {
				    String str1 = topseq.getSequence().substring(i-2,i+1);
				    String str2 = seq.getSequence().substring(i-2,i+1);

				    String res1 = ResidueProperties.codonTranslate(str1);
				    String res2 = ResidueProperties.codonTranslate(str2);

				    if (res2 == null) {
					res2 = "X";
				    }
					
				    if (av.getCsmMatrix() != null && av.getCSMExons() == true) {
					Hashtable names = av.getCsmNames();


					if (names.containsKey(str1) &&
					    names.containsKey(str2)) {
					    int pos1 = (Integer) names.get(str1);
					    int pos2 = (Integer) names.get(str2);
					    
					    double value = av.getCsmMatrix()[pos1][pos2];
					    
					    if (value < 0) {
						g.setColor(new Color((int)(255*value/av.getCsmMin()),0,0));
					    } else if (value > 0)  {
						g.setColor(new Color(0,(int)(255*value/av.getCsmMax()),0));
					    } else {
						g.setColor(grayGreen);
					    }
					} else {
					    g.setColor(Color.pink);
					}
				    } else {
				    				    
					if (res2 != null) {
					    if (res1.equals(res2)) {
						g.setColor(grayBlue);
					    } else {
						g.setColor(Color.lightGray);
					    }
					}
				    }
				    if (str2.equals("TAA") ||
					str2.equals("TGA") ||
					str2.equals("TAG")) {
					g.setColor(Color.yellow);			   
				    }
				    g.fillRect(newpixel-(int)(width*2),y1,(int)(width)*3+1,height-4);
				    g.setColor(Color.black);
				    g.drawString(res2,newpixel-(int)(width),y1+3*height/4);
				}
			  
			    }
			    if (sf.getStrand() == -1) {
				int pos = (sf.getEnd() - i - (3-phase))%3;
				
				if (pos == 0) {
				    String str1 = topseq.getSequence().substring(i-2,i+1);
				    String str2 = seq.getSequence().substring(i-2,i+1);
				    
				    str1 = ResidueProperties.reverseComplement(str1);
				    str2 = ResidueProperties.reverseComplement(str2);

				    String res1 = ResidueProperties.codonTranslate(str1);
				    String res2 = ResidueProperties.codonTranslate(str2);
				    
				    if (res2 == null) {
					res2 = "X";
				    }

				    if (av.getCsmMatrix() != null && av.getCSMExons() == true) {
					Hashtable names = av.getCsmNames();

					if (names.containsKey(str1) &&
					    names.containsKey(str2)) {
					    int pos1 = (Integer) names.get(str1);
					    int pos2 = (Integer) names.get(str2);
					    
					    double value = av.getCsmMatrix()[pos1][pos2];
					    
					    //System.out.println("Csm " + value + " " + av.getCsmMax());
					    if (value < 0) {
						g.setColor(new Color((int)(255*value/av.getCsmMin()),0,0));
					    } else if (value > 0) {
						g.setColor(new Color(0,(int)(255*value/av.getCsmMax()),0));
					    } else {
						g.setColor(grayGreen);
					    }
					} else {
					    g.setColor(Color.pink);
					}
				    } else {
					if (res2 != null) {
					    if (res1.equals(res2)) {
						g.setColor(grayBlue);
					    } else {
						g.setColor(Color.lightGray);
					    }
					}
				    }
				    if (str2.equals("TAA") ||
					str2.equals("TGA") ||
					str2.equals("TAG")) {
					g.setColor(Color.yellow);			   
				    }
				    g.fillRect(newpixel-(int)(width*2),y1,(int)(width)*3+1,height-4);
				    g.setColor(Color.black);
				    g.drawString(res2,newpixel-(int)(width),y1+3*height/4);
				}
			    }
			}
		    }
		}
		pixel = newpixel;

	    }
	    i++;
	}

	int j = 0;

// 	if (inserts != null) {
// 	    while (j < inserts.size()) {
// 		Hashtable ins  = (Hashtable)inserts.elementAt(j);

// 		int coord = ((Integer)(ins.get("Coord"))).intValue();

// 		String insert = (String)ins.get("String");

// 		if (coord >= start && coord <= end) {

// 		    if (insert.length() % 3 == 0) {
// 			g.setColor(Color.magenta);
// 		    } else {
// 			g.setColor(Color.yellow);
// 		    }
			
// 		    g.fillRect(x1 + (int)(width*(coord-start)),y1,2,insert.length());
// 		}
// 		j++;
// 	    }
// 	}
			     
    }
}
